import sys
import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QMainWindow, QPlainTextEdit, QFileSystemModel, QListView
from ui.ui_main import Ui_MainWindow
from logconfig.logconfig import logger

# 这里可以将修改后的 get_frame_pic 函数复制过来
def get_video_frame_count(video_path):
    """
    获取视频的总帧数
    :param video_path: 视频文件路径
    :return: 视频的总帧数
    """
    # 打开视频文件
    cap = cv2.VideoCapture(video_path)

    if not cap.isOpened():
        logger.error(f"无法打开视频文件: {video_path}")
        return -1

    # 获取总帧数
    frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

    # 释放视频对象
    cap.release()

    return frame_count

def is_video_file(file_path):
    """判断文件是否为视频文件"""
    video_extensions = [".mp4", ".avi", ".mkv", ".mov", ".flv", ".wmv"]  # 支持的视频扩展名
    return os.path.isfile(file_path) and any(file_path.lower().endswith(ext) for ext in video_extensions)

def get_frame_pic(video_path, frame_count, frame_number):
    """显示指定帧"""
    # 检查帧号是否在有效范围内
    if frame_number < 1 or frame_number > frame_count:
        logger.error(f"帧号 {frame_number} 超出有效范围（1 - {frame_count}）")
        return None

    # 打开视频文件
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        logger.error(f"无法打开视频文件: {video_path}")
        return None
    # 跳转到指定帧
    cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number - 1)  # 帧号从 0 开始
    ret, frame = cap.read()

    if not ret:
        logger.error(f"无法读取帧: {frame_number}")
        cap.release()
        return None
    cap.release()
    # 将 OpenCV 的 BGR 格式转换为 RGB 格式
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # 将 OpenCV 图片转换为 PyQt5 图片
    height, width, channel = frame_rgb.shape
    bytes_per_line = 3 * width
    q_image = QImage(frame_rgb.data, width, height, bytes_per_line, QImage.Format_RGB888)

    # 将 QImage 转换为 QPixmap 并显示
    pixmap = QPixmap.fromImage(q_image)
    return pixmap

class Stream(QObject):
    newText = pyqtSignal(str)

    def write(self, text):
        self.newText.emit(str(text))

class GetFramePicThread(QThread):
    frame_pic_ready = pyqtSignal(object)

    def __init__(self, video_path, frame_count, frame_number):
        super().__init__()
        self.video_path = video_path
        self.frame_count = frame_count
        self.frame_number = frame_number

    def run(self):
        try:
            img = get_frame_pic(self.video_path, self.frame_count, self.frame_number)
            if img is not None:
                self.frame_pic_ready.emit(img)
            else:
                logger.error("未能获取到指定帧的图片")
        except Exception as e:
            logger.error(f"获取帧图片时发生错误: {e}")

class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.thread = QThread
        self.setupUi(self)
        self.setWindowTitle("性能测试数帧工具")
        self.setFixedSize(1307, 959)
        self.init_log_editor()
        self.cal_hz = 0
        self.folder_path = ''
        self.video_path = ''
        self.frame_count = 0
        self.model = QFileSystemModel()
        self.listmodel = QStringListModel()
        self.init_ui()

    def init_ui(self):
        """初始化UI界面"""
        self.init_radio_btn()
        self.init_frame_pic()

    def init_frame_pic(self):
        """初始化图片显示区域"""
        self.frame_pic.setAlignment(Qt.AlignmentFlag.AlignCenter)  # 图片居中显示
        self.frame_pic.setStyleSheet("background-color: black;")  # 设置背景色（可选）
        self.frame_pic_layout.addWidget(self.frame_pic, 0, 0)  # 添加到布局中
        self.frame_pic_layout.setRowStretch(0, 1)  # 设置拉伸因子
        self.frame_pic_layout.setColumnStretch(0, 1)

    def init_radio_btn(self):
        """初始化帧数计算选择按钮"""
        self.choose_60hz_btn.setChecked(False)
        self.choose_120hz_btn.setChecked(True)
        self.cal_hz = 120
        self.choose_240hz_btn.setChecked(False)

    def init_log_editor(self):
        """初始化日志编辑器"""
        self.log_editor.setReadOnly(True)
        self.log_editor.setLineWrapMode(QPlainTextEdit.WidgetWidth)
        logger.add(self.write_log)
        sys.stdout = Stream(newText=self.on_update_text)
        sys.stderr = Stream(newText=self.on_update_text)

    def init_file_tree_view(self, folder_path):
        """初始化文件树视图"""
        try:
            if not folder_path:
                logger.error("文件夹路径为空")
                return
            self.model.setRootPath(folder_path)
            self.file_tree_view.setModel(self.model)
            self.file_tree_view.setRootIndex(self.model.index(folder_path))
            self.file_tree_view.setHeaderHidden(True)
            for i in range(1, self.model.columnCount()):
                self.file_tree_view.hideColumn(i)
        except Exception as e:
            logger.error(f"初始化文件树视图时发生错误: {e}")

    def init_frame_list_view(self, video_path, frame_count):
        """初始化帧列表视图"""
        try:
            self.frame_list_view.setEditTriggers(QListView.NoEditTriggers)
            data_list = [f"第{i + 1}帧" for i in range(frame_count)]
            self.listmodel.setStringList(data_list)
            self.frame_list_view.setModel(self.listmodel)
            if self.listmodel.rowCount() > 0:
                first_index = self.listmodel.index(0)
                self.frame_list_view.setCurrentIndex(first_index)
                self.frame_list_view.selectionModel().select(first_index, QItemSelectionModel.SelectionFlag.Select)
            self.frame_list_view.selectionModel().selectionChanged.connect(self.on_selection_changed)
        except Exception as e:
            logger.error(f"初始化帧列表视图时发生错误: {e}")

    def update_pic(self, frame_number):
        """更新图片"""
        logger.info(f"视频路径: {self.video_path}")
        logger.info(f"总帧数: {self.frame_count}")
        logger.info(f"选中的帧号: {frame_number}")

        if not self.video_path or self.frame_count <= 0:
            logger.error("视频路径或总帧数无效")
            return

        self.thread = GetFramePicThread(self.video_path, self.frame_count, frame_number)
        self.thread.frame_pic_ready.connect(self.show_frame_pic)
        self.thread.start()

    def show_frame_pic(self, img):
        """显示帧图片"""
        try:
            if img.isNull():
                logger.error("未能获取到指定帧的图片")
                return

            # 获取 frame_pic 的当前大小
            label_size = self.frame_pic.size()

            # 等比例缩放图片
            scaled_pixmap = img.scaled(
                label_size,
                Qt.AspectRatioMode.KeepAspectRatio,  # 等比例缩放
                Qt.TransformationMode.SmoothTransformation  # 平滑缩放
            )

            # 设置图片到 QLabel
            self.frame_pic.setPixmap(scaled_pixmap)
            self.frame_pic.update()  # 强制刷新
        except Exception as e:
            logger.error(f"显示帧图片时发生错误: {e}")

    def on_selection_changed(self, selected, deselected):
        """当选中项变化时触发"""
        try:
            selected_indexes = selected.indexes()
            if selected_indexes:
                selected_item = selected_indexes[0].data()
                selected_item_index = selected_indexes[0].row()
                logger.info(f"选中的项: {selected_item}")
                logger.info(f"选中项的索引: {selected_item_index}")
                self.update_pic(selected_item_index + 1)  # 帧号从 1 开始
            else:
                logger.info("未选中任何项")
        except Exception as e:
            logger.error(f"报错信息如下: {str(e)}")

    def on_update_text(self, text):
        """更新日志"""
        cursor = self.log_editor.textCursor()
        cursor.movePosition(cursor.End)
        cursor.insertText(text)
        self.log_editor.setTextCursor(cursor)
        self.log_editor.ensureCursorVisible()

    def write_log(self, message):
        """写入日志"""
        self.log_editor.appendPlainText(str(message).strip())

    def click60hz_btn(self):
        """选中60hz计算"""
        self.cal_hz = 60
        logger.info(self.cal_hz)

    def click120hz_btn(self):
        """选中120hz计算"""
        self.cal_hz = 120
        logger.info(self.cal_hz)

    def click240hz_btn(self):
        """选中240hz计算"""
        self.cal_hz = 240
        logger.info(self.cal_hz)

    def choose_folder(self):
        """选择文件夹"""
        try:
            from PyQt5.QtWidgets import QFileDialog
            folder_path = QFileDialog.getExistingDirectory(self, '选择文件夹')
            if folder_path and os.path.isdir(folder_path):
                logger.info(f'所选文件夹路径: {folder_path}')
                self.folder_path = folder_path
                self.init_file_tree_view(self.folder_path)
            else:
                logger.error('无效的文件夹路径')
        except Exception as e:
            logger.error(f"选择文件夹时发生错误: {e}")

    def choose_file(self, index):
        """选择文件"""
        try:
            file_choose_path = self.model.filePath(index)
            logger.info(file_choose_path)
            if is_video_file(file_choose_path):
                self.video_path = file_choose_path
                frame_count = get_video_frame_count(file_choose_path)
                self.frame_count = frame_count
                logger.info("视频总帧数为:{}".format(frame_count))
                self.init_frame_list_view(file_choose_path, frame_count)
        except Exception as e:
            logger.error(f"选择文件时发生错误: {e}")

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())